---
id: worklets
sidebar_label: Worklets
sidebar_position: 1
---

# Worklets

Worklet is a short-running JavaScript function that can be moved and executed across different Javascript Runtimes. Reanimated uses worklets to calculate view styles and react to events on the UI thread.

## Defining worklets

You can create your own worklets using the `'worklet'` directive at the top of a function.

```javascript
function myWorklet() {
  'worklet';
  console.log('Hello from a worklet');
}
```

## Workletization

The [Worklets Babel plugin](https://docs.swmansion.com/react-native-worklets/docs/worklets-babel-plugin/about) looks for functions marked with the `'worklet'` directive and converts them into serializable objects. We call this process [workletization](/docs/fundamentals/glossary#to-workletize). These objects can then be copied and run over on the UI thread.

Most of the time when working with Reanimated and [Gesture Handler](https://docs.swmansion.com/react-native-gesture-handler/) the code is automatically workletized and run on the UI thread by default.

```javascript
import { useAnimatedStyle } from 'react-native-reanimated';

function App() {
  const style = useAnimatedStyle(() => {
    // Running on the UI thread
    return { opacity: 0.5 };
  });
}
```

## Running worklets on the UI Runtime (UI Thread)

You can use [`scheduleOnUI`](https://docs.swmansion.com/react-native-worklets/docs/threading/scheduleOnUI) to manually schedule worklet execution on the UI Runtime:

```javascript
function myWorklet() {
  'worklet';
  console.log('Hello from the UI thread');
}

function onPress() {
  scheduleOnUI(myWorklet);
}
```

You can pass arguments to worklets.

```javascript
function myWorklet(greeting) {
  'worklet';
  console.log(`${greeting} from the UI thread`);
}

function onPress() {
  scheduleOnUI(myWorklet, 'Howdy');
}
```

## Running functions from worklets

You can run functions on the RN Runtime (JS thread) from the UI Runtime (UI thread) with [`scheduleOnRN`](https://docs.swmansion.com/react-native-worklets/docs/threading/scheduleOnRN). Most frequently used to call functions that aren't marked with a `'worklet';` directive (i.e. most third-party libraries) or to update the React state.

```javascript
import { router } from 'expo-router';
import { Gesture } from 'react-native-gesture-handler';

function App() {
  const tap = Gesture.Tap().onEnd(() => {
    // i'm a worklet too!
    // highlight-next-line
    scheduleOnRN(router.back);
  });
}
```

Functions passed to `scheduleOnRN` must be defined in the [JavaScript thread](/docs/fundamentals/glossary#javascript-thread) scope, i.e. in the component body or the global scope. This code won't work because `myFunction` is defined in the `withTiming` callback, which is only executed in the [UI Runtime](https://docs.swmansion.com/react-native-worklets/docs/fundamentals/runtimeKinds#ui-runtime):

```javascript
function App() {
  const tap = Gesture.Tap().onEnd(() => {
    // myFunction is defined on the UI runtime 🚨
    const myFunction = () => {};
    scheduleOnRN(myFunction); // 💥
  });
}
```

## Hoisting

Functions marked with `'worklet'` aren't [hoisted](https://developer.mozilla.org/en-US/docs/Glossary/Hoisting). Besides affecting hoisting, the `'worklet'` directive has no effect on the [RN Runtime](https://docs.swmansion.com/react-native-worklets/docs/fundamentals/runtimeKinds#rn-runtime).

## Capturing closure

Worklets are [closures](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures). They can access variables declared outside of their own scope. Only variables referenced in the worklet body will be captured inside the worklet scope.

```javascript
const width = 135.5;

function otherWorklet() {
  'worklet';
  console.log('Captured width is', width);
}
```

Capturing large JavaScript objects inside of a worklet can lead to performance issues.

```javascript
const theme = {...}; // theme is a large object

function myWorklet() {
  'worklet';
  console.log(theme.color); // 🚨 referenced `color` but captured the whole `theme` object
}
```

You can get around this problem by first assigning the prop you want to use to a separate variable.

```javascript
const theme = {...};
const color = theme.color;

function myWorklet() {
  'worklet';
  console.log(color); // ✅ captured only `color`
}
```

## Passing data to worklets

Worklets can return data within the same thread.

```javascript
function returningWorklet() {
  'worklet';
  return "I'm back"; // on the UI thread
}

function someWorklet() {
  'worklet';
  const what = returningWorklet(); // still on the UI thread
  console.log('On the UI thread, other worklet says', what);
}
```

To pass data between UI and JS thread we use [shared values](/docs/fundamentals/glossary#shared-value).

```javascript
import { useSharedValue } from 'react-native-reanimated';

function App() {
  const width = useSharedValue(100);

  function myWorklet() {
    'worklet';
    width.value += 50;
  }

  useEffect(() => {
    console.log(width.value); // available on both JS and UI thread
  }, []);
}
```

## Using worklets on the Web

There's no separate UI thread available on the Web. Because of that, when Reanimated runs in the browser, worklets are resolved to plain JavaScript functions.

However, the `'worklet'` directive is still necessary on the Web, because Reanimated relies on the Worklets Babel plugin to capture dependencies inside worklet functions.

## Other worklet runtimes

Worklets can run in other runtimes than the one provided by React Native Worklets. For example [VisionCamera](https://github.com/mrousavy/react-native-vision-camera) and [LiveMarkdown](https://github.com/Expensify/react-native-live-markdown) create their own worklet runtimes.

You can create your own worklet runtimes with [`createWorkletRuntime`](https://docs.swmansion.com/react-native-worklets/docs/threading/createWorkletRuntime) function.
